package redis

import (
	"gamesdk/common/log"
	"gamesdk/common/redis/redis-cluster"
	"gamesdk/common/redis/redis-one"
	"gamesdk/common/transform"
	"runtime"
	"time"
)

type session interface {
	Get(key string) (string, error)
	Set(key string, value interface{}) error
	SetByTime(key string, value interface{}, tm int) error
	DEL(Key string) (int, error)
	SetNx(key string, value interface{}) (bool, error)
	GETSET(key string, value interface{}) (string, error)
}

var g_sess session

//初始化不带集群的redis
func InitRedisPass(ip, p string) (err error) {
	if g_sess == nil {
		g_sess, err = redis_one.CreateRedisManager(ip, p)
	}
	return nil
}

//初始化集群redis
func InitRedisCluster(ip []string, pass string) error {
	if g_sess == nil {
		redis, err := redis_cluster.InitRedisPass(ip, pass)
		if err != nil {
			log.Error(err.Error())
			return err
		}
		g_sess = redis
	}
	return nil
}

func Get(key string) (string, error) {
	return g_sess.Get(key)
}

func Set(key string, value string) error {
	return g_sess.Set(key, value)
}

func SetByTime(key string, value string, tm int) error {
	return g_sess.SetByTime(key, value, tm)
}

func DEL(key string) (int, error) {
	return g_sess.DEL(key)
}

func SetNx(key string, value interface{}) (bool, error) {
	return g_sess.SetNx(key, value)
}

func GETSET(key string, value interface{}) (string, error) {
	return g_sess.GETSET(key, value)
}

type RedisLock struct {
	timeOut int64 //超时时间
	tim     int64 //设置的时间key
}

func NewRedisLock() *RedisLock {
	return &RedisLock{
		timeOut: 240 * 1000000 * 1000,
		tim:     0,
	}
}
func (this *RedisLock) Lock(key string) error {
	for {
		this.tim = time.Now().UnixNano() + this.timeOut + 1
		isExists, err := g_sess.SetNx(key, this.tim)
		if err != nil {
			log.Debug(err.Error())
			return err
		}
		if !isExists {
			tt, err := g_sess.Get(key)
			if err != nil {
				log.Error(err.Error())
				return err
			}
			oldTime, err := transform.InterToInt64(tt)
			if err != nil {
				log.Error(err.Error())
				return err
			}
			now := time.Now().UnixNano()
			if now > oldTime {
				this.tim = now + this.timeOut + 1
				old_s, err := g_sess.GETSET(key, this.tim)
				if err != nil {
					log.Error(err.Error())
					return err
				}
				old, err := transform.InterToInt64(old_s)
				if err != nil {
					log.Error(err.Error())
					return err
				}

				if err != nil {
					if err.Error() == "redigo: nil returned" {
						time.Sleep(time.Millisecond * 1)
						runtime.Gosched()
						continue
					}
					log.Error(err.Error())
					return err
				}
				if now > old {
					log.Warn("分布式锁超时了")
					return nil
				}
			}
		} else {
			return nil
		}
		time.Sleep(time.Millisecond * 1)
		runtime.Gosched()
	}
}

func (this *RedisLock) UnLock(key string) {
	now := time.Now().UnixNano()
	if now < this.tim {
		g_sess.DEL(key)
	}
}
